#include <modbus.h>
#include <modbus-tcp.h>
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <errno.h>
#include <sys/shm.h>
#include <sys/msg.h>
#include <string.h>

key_t key;
modbus_t *cxt;
struct buf
{
    uint16_t data[32];
};
struct msgbuf
{
    long typer;
    int ch;
};
void *headler(void *sig);
int main(int argc, char const *argv[])
{

    // 创建实例
    cxt = modbus_new_tcp("192.168.51.234", 502);
    // 输入id号
    int slave = 1;
    modbus_set_slave(cxt, slave);
    // 建立连接
    modbus_connect(cxt);

    pthread_t tid;
    tid = pthread_create(&tid, NULL, headler, NULL);
    if (tid < 0)
    {
        perror("tid err\n");
        return -1;
    }
    printf("aaa\n");
    while (1)
    {
        key_t key;
        // 1.创建唯一key值  ftok
        key = ftok("./app", 'a');
        if (key < 0)
        {
            perror("key1 err\n");
            return -1;
        }
        printf("key:%d\n", key);
        // 2.创建消息队列
        int msgid = msgget(key, IPC_CREAT | IPC_EXCL | 0666);
        if (msgid < 0)
        {
            if (errno == EEXIST)
            {
                printf("重新打开\n");
                msgid = msgget(key, 0666);
                printf("%d\n",msgid);
            }
            else
            {
                perror("msgget err\n");
                return -1;
            }
        }
        // 3.消息队列读取消息
        struct msgbuf msg1;
        // 读取类型为100里的数据
        if (msgrcv(msgid, &msg1, sizeof(msg1) - sizeof(long), 100, 0) < 0)
        {
            perror("recv2 err");
        }
        printf("msg.type:%ld  a:%d\n", msg1.typer, msg1.ch);
        // printf("a:%d\n", msg1.ch);
        int a = msg1.ch;
        // 清空
        // memset(&msg1, 0, sizeof(msg1));
        // 读取类型为200里的数值
        if (msgrcv(msgid, &msg1, sizeof(msg1) - sizeof(long), 200, 0) < 0)
        {
            perror("recv2 err");
        }
        printf("msg.type:%ld  b:%d\n", msg1.typer, msg1.ch);
        // printf("b:%d\n", msg1.ch);
        int b = msg1.ch;

        if (a == 0)
        {
            if (b == 0)
            {
                modbus_write_bit(cxt, 0, 0);
            }

            else if (b == 1)
            {
                modbus_write_bit(cxt, 0, 1);
            }
        }
        if (a == 1)
        {
            if (b == 0)
            {
                modbus_write_bit(cxt, 1, 0);
            }

            else if (b == 1)
            {
                modbus_write_bit(cxt, 1, 1);
            }
            msgctl(msgid, IPC_RMID, NULL);
        }
    }
    modbus_free(cxt);
    modbus_close(cxt);
    return 0;
}

void *headler(void *sig)
{
    struct buf *p = NULL;
    // 1.创建唯一key值  ftok
    key = ftok("./cc", 'a');
    if (key < 0)
    {
        perror("key err\n");
        return NULL;
    }
    printf("key:%d\n", key);
    // 2.创建或打开共享内存
    int shmid = shmget(key, 64, IPC_CREAT | IPC_EXCL | 0666);
    if (shmid < 0)
    {

        if (errno == EEXIST)
        {
            printf("file eixts");
            shmid = shmget(key, 64, 0666);
        }
        else
        {
            perror("shmget err\n");
            return NULL;
        }
    }
    // 3.映射共享内存
    p = shmat(shmid, NULL, 0);
    if (p == (void *)-1)
    {
        perror("shmat err\n");
        return NULL;
    }
    while (1)
    {

        // 起始地址
        int addr = 0;
        // 要读取的数量
        int nb = 2;

        if (modbus_read_registers(cxt, addr, nb, p->data) < 0)
        {
            perror("recv err");
        }
        printf("temp:%d\n", p->data[0]);
        printf("s:%d\n", p->data[1]);
        sleep(3);
    }
    // 4.取消映射
    shmdt(p);
    // 5.删除共享内存
    shmctl(shmid, IPC_RMID, NULL);
}
